package cn.bugstack.ai_autoclassification_qwen.service.impl;

import cn.bugstack.ai_autoclassification_qwen.domain.Category;
import cn.bugstack.ai_autoclassification_qwen.domain.Product;
import cn.bugstack.ai_autoclassification_qwen.dto.ClassifyResponse;
import cn.bugstack.ai_autoclassification_qwen.dto.ModelCategoryResult;
import cn.bugstack.ai_autoclassification_qwen.repository.CategoryRepository;
import cn.bugstack.ai_autoclassification_qwen.repository.ProductRepository;
import cn.bugstack.ai_autoclassification_qwen.service.ProductClassificationService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.model.Media;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.stereotype.Service;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ProductClassificationServiceimpl implements ProductClassificationService {

    // 调用大模型的客户端对象
    private final ChatModel chatModel;

    // 商品表对应的JPA仓储
    private final ProductRepository productRepository;

    // 类别表对应的JPA仓储
    private final CategoryRepository categoryRepository;

    private final RestTemplate restTemplate;

    private final WebClient webClient;

    // Jackson 的 JSON 解析工具，用于 把模型返回的 JSON 字符串转成 Java 对象
    private final ObjectMapper mapper = new ObjectMapper();

    public ClassifyResponse classifyProduct(Long productId) {
        log.info("productId:{}", productId);
        Product product = productRepository.findById(productId)
                .orElseThrow(() -> new RuntimeException("商品不存在: " + productId));

        byte[] imageBytes = webClient.get()
                .uri(product.getImageUrl())
                .retrieve()
                .bodyToMono(byte[].class)
                .block();
        System.out.println(product.getImageUrl());

        List<Category> categories = categoryRepository.findAll();
        String categoryList = categories.stream()
                .map(c -> c.getCategoryCode() + " - " + c.getCategoryName())
                .collect(Collectors.joining("\n"));

        String systemPrompt = """
                你是一个电商商品分类助手。
                你会看到一个商品的文字描述和图片，以及一个“类目列表”。
                你的任务是：结合图片和文本信息，从类目列表中选出**最合适的一个类目**。
                类目名称只用类目列表中已经有的，不要含有多余的文字。
                返回结果时必须只用 JSON 格式，不要输出多余文字。
                JSON 格式如下：
                {
                  "categoryCode": "类目编号字符串",
                  "categoryName": "类目名称字符串"
                }
                如果无法确定，请选出最接近的类目，不要返回空值。
                """;
        // 如果可以匹配的类别名称涉及到性别，而商品名称没有明显的性别信息，那么你需要识别模特的身体特征来对商品进行正确的性别归类

        System.out.println(categoryList);

        String userPrompt = """
                下面是一个商品，请根据图片和文本内容在给定的类目列表中选择一个最合适的类目，类目不要含有多余的文字：

                商品名称：
                %s

                商品描述：
                %s

                商品图片：已作为图片内容传给你（不在文本中）

                类目列表（每一行是“编号 - 名称”）：
                %s

                请严格按照之前约定的 JSON 结构返回，不要用 Markdown 代码块，不要加注释。
                """.formatted(
                product.getName(),
                product.getDescription() == null ? "" : product.getDescription(),
                categoryList
        );

        Prompt prompt = new Prompt(
                List.of(
                        new SystemMessage(systemPrompt),
                        new UserMessage(
                                userPrompt,
                                List.of(new Media(MimeTypeUtils.IMAGE_JPEG,
                                        new ByteArrayResource(imageBytes)))
                        )
                )
        );

        ChatResponse response = chatModel.call(prompt);

        String content = response.getResult().getOutput().getContent();

        ModelCategoryResult result;

        try {
            result = mapper.readValue(content, ModelCategoryResult.class);
        } catch (Exception e) {
            throw new RuntimeException("模型返回的 JSON 无法解析: " + content, e);
        }

        // 保存结果
        product.setPredictedCategoryCode(result.getCategoryCode());
        product.setPredictedCategoryName(result.getCategoryName());
        productRepository.save(product);

        return ClassifyResponse.builder()
                .productId(product.getId())
                .productName(product.getName())
                .categoryCode(result.getCategoryCode())
                .categoryName(result.getCategoryName())
                .rawModelOutput(content)
                .build();
    }
}

